package com.ruoyi.project.remoteControl.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.project.remoteControl.config.MqttConfig;
import com.ruoyi.project.remoteControl.domain.DeviceAliveInfo;
import com.ruoyi.project.remoteControl.mapper.DeviceAliveInfoMapper;
import com.ruoyi.project.remoteControl.service.RemoteControlService;
import com.ruoyi.project.remoteControl.utils.AbsolutePathGetter;
import com.ruoyi.project.remoteControl.utils.SessionInfoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.awt.*;
import java.net.URI;
import java.util.Objects;


@Service
@Slf4j
public class RemoteControlServiceImpl implements RemoteControlService {
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    AbsolutePathGetter absolutePathGetter;
    @Autowired
    SessionInfoUtils sessionInfoUtils;
    @Autowired
    MqttConfig mqttClient;
    @Autowired
    DeviceAliveInfoMapper deviceAliveInfoMapper;
    
    // window环境下主控web文件保存路径
    @Value("${path.htmlFilePath}")
    String relativeHtmlPath;
    // MQTT订阅主题
    @Value("${mqtt.topic.remoteControlTopic}")
    String remoteControlTopic;
    // 当前工作环境
    @Value("${workingEnv}")
    private String workingEnv;
    // 服务器IP
    @Value("${serverHost}")
    private String serverHost;
    // 服务器域名
    @Value("${serverUrl}")
    private String serverUrl;
    
    //  通过公网IP进行指令发送
    @Override
    public JSONObject remoteConnect(String remoteDevicePublicIP) {
        String url = remoteDevicePublicIP + "/installService";
        JSONObject clientSessionInfo = restTemplate.postForObject(url, "InstallService", JSONObject.class);
        return clientSessionInfo;
    }

    @Override
    public String remoteDisConnect(String remoteDevicePublicIP) {
        String url = remoteDevicePublicIP + "/uninstallService";
        String response = restTemplate.postForObject(url, "UninstallService", String.class);
        return response;
    }

    /**
     * 通过MQTT发起远控
     * @param deviceClientId
     * @return
     */
    @Override
    public JSONObject mqttRemoteConnect(String deviceClientId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("deviceClientId",deviceClientId);
        jsonObject.put("instruction","install");
        String mqttInstruction = jsonObject.toJSONString();
        try {
            // 发送MQTT消息
            mqttClient.publish(0,false,remoteControlTopic,mqttInstruction);
            // 设置计时器
            int timeCounter = 0;
            while (!sessionInfoUtils.isInstallSuccess(deviceClientId)){
                Thread.sleep(100);
                timeCounter += 100;
                // 处理超时抛出异常
                if (timeCounter > 5000){
                    throw new RuntimeException("远控发起失败！");
                }
            }
            // 获取被控端返回的sessionInfo
            JSONObject sessionInfo = sessionInfoUtils.getSessionInfo(deviceClientId);
            String url = "";
            // 判断当前工作环境并生成远控url添加至sessionInfo中
            if (Objects.equals(workingEnv, "dev")){
                String header = "file:///";
                // 获取文件绝对路径
                String absoluteHtmlPath = absolutePathGetter.getAbsolutePath(relativeHtmlPath);
                // 拼接远控会话参数
                String params = "?address=" + sessionInfo.getString("address") + "&cid=" + sessionInfo.getString("cid");
                url = header + absoluteHtmlPath + params;
                sessionInfo.put("url",url);
            }
            if (Objects.equals(workingEnv, "prod")){
                String header = "http://" + serverUrl + "/sunlogin_host/demo/demo-sunlogin-sdk.html";
//                String header = serverHost + "/sunlogin_host/demo/demo-sunlogin-sdk.html";
                // 拼接远控会话参数
                String params = "?address=" + sessionInfo.getString("address") + "&cid=" + sessionInfo.getString("cid");
                url = header + params;
                sessionInfo.put("url",url);
            }
            // 远控发起成功后立即更新被控端的status(否则等待被控端发送存活信息时才更新就太慢了)
            QueryWrapper<DeviceAliveInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("DEVICE_CLIENT_ID",deviceClientId);
            DeviceAliveInfo deviceAliveInfo = new DeviceAliveInfo();
            deviceAliveInfo.setStatus("2");
            deviceAliveInfoMapper.update(deviceAliveInfo,queryWrapper);
            
            return sessionInfo;
        } catch (Exception e) {
            e.printStackTrace();
            
            // 远控发起失败时发送mqtt指令清空被控端的对话信息日志，防止远控失败后被控端的日志非空而导致远控状态判断异常的问题
            JSONObject clearLogJsonObject = new JSONObject();
            clearLogJsonObject.put("deviceClientId",deviceClientId);
            clearLogJsonObject.put("instruction","clearLog");
            String clearLogMqttInstruction = clearLogJsonObject.toJSONString();
            mqttClient.publish(0,false,remoteControlTopic,clearLogMqttInstruction);
            
            return null;
        }
    }

    @Override
    public String mqttRemoteDisconnect(String deviceClientId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("deviceClientId",deviceClientId);
        jsonObject.put("instruction","uninstall");
        String mqttInstruction = jsonObject.toJSONString();
        try {
            // 发送MQTT消息
            mqttClient.publish(0,false,remoteControlTopic,mqttInstruction);
            // 设置计时器
            int timeCounter = 0;
            while (!sessionInfoUtils.isUninstallSuccess(deviceClientId)){
                Thread.sleep(100);
                timeCounter += 100;
                // 处理超时抛出异常
                if (timeCounter > 5000){
                    throw new RuntimeException("远控断开失败！");
                }
            }
            // 日志保存更新后的sessionInfo的msg
            log.info(sessionInfoUtils.getSessionInfo(deviceClientId).getString("msg"));
            // 从SessionInfo.sessionList中删除对应会话信息
            sessionInfoUtils.deleteSessionInfo(deviceClientId);
            // 远控结束成功后立即更新被控端的status(否则等待被控端发送存活信息时才更新就太慢了)
            QueryWrapper<DeviceAliveInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("DEVICE_CLIENT_ID",deviceClientId);
            DeviceAliveInfo deviceAliveInfo = new DeviceAliveInfo();
            deviceAliveInfo.setStatus("1");
            deviceAliveInfoMapper.update(deviceAliveInfo,queryWrapper);
            
            return "远控断开成功！";
        } catch (Exception e) {
            e.printStackTrace();
            return "远控断开失败！";
        }
    }

    @Override
    public void openRemoteHtml(String deviceClientId) {
        JSONObject sessionInfo =sessionInfoUtils.getSessionInfo(deviceClientId);
        String address = (String) sessionInfo.get("address");
        String cid = (String) sessionInfo.get("cid");
        if (Desktop.isDesktopSupported()) {
            Desktop desktop = Desktop.getDesktop();
            try {
                String header = "http://tbmonitor.gzport.com/sunlogin_host/demo/demo-sunlogin-sdk.html";
                String params = "?address=" + address + "&cid=" + cid;
                String path = header + params;
                URI uri = new URI(path);
                desktop.browse(uri);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
